package dmmm.main;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;

import javax.swing.*;

import dmmm.components.*;
import dmmm.shemes.*;

@SuppressWarnings("serial")
public class RegistersFrame extends JFrame {

	private JTextField[] regsTextFields;
	private static String[] registers = { "MAR:", "MDR:", "DWH:", "DWL:",
			"PC:", "IR0:", "IR1:", "IR2:", "IR3:", "SP:", "GPRAR:", "CW:",
			"AB:", "BB:", "AW:", "BW:", "IMR:", "BR:", "IVTP:" };
	private static String[] ffs = { "PSWN:", "PSWZ:", "PSWC:", "PSWV:",
			"PSWI:", "PSWT:", "PSWL0:", "PSWL1:", "PSWL2:" };
	private REG[] allRegs;
	private RSFF[] allFF;
	private boolean error;
	private JDialog greska;
	private JDialog potvrda;
	//prozor za prikaz registara ima referencu na glavni prozor jer ako se promeni vrednost nekog registra mora da se update glavni prozor za prikaz da se izmenjena vrednost odmah vidi u MAIN prozor
	private Main myMain;

	public RegistersFrame(Main m) {
		myMain = m;
		regsTextFields = new JTextField[60];

		setTitle("Registri");
		Color bgColor = Color.WHITE;
		setBackground(bgColor);

		GPR gpr = Adr1.GPR();
		allRegs = new REG[19];
		allRegs[0] = Bus1.RegMAR();
		allRegs[1] = Bus1.RegMDR();
		allRegs[2] = Bus1.RegDWH();
		allRegs[3] = Bus1.RegDWL();
		allRegs[4] = Fetch1.RegPC();
		allRegs[5] = Fetch1.RegIR0();
		allRegs[6] = Fetch1.RegIR1();
		allRegs[7] = Fetch1.RegIR2();
		allRegs[8] = Fetch1.RegIR3();
		allRegs[9] = Adr1.RegSP();
		allRegs[10] = Adr1.RegGPRAR();
		allRegs[11] = Adr1.RegCW();
		allRegs[12] = Exec1.RegAB();
		allRegs[13] = Exec1.RegBB();
		allRegs[14] = Exec1.RegAW();
		allRegs[15] = Exec1.RegBW();
		allRegs[16] = Intr1.RegIMR();
		allRegs[17] = Intr3.RegBR();
		allRegs[18] = Intr3.RegIVTP();

		allFF = new RSFF[9];
		allFF[0] = Exec2.NRSFF();
		allFF[1] = Exec2.ZRSFF();
		allFF[2] = Exec2.CRSFF();
		allFF[3] = Exec2.VRSFF();
		allFF[4] = Exec2.IRSFF();
		allFF[5] = Exec2.TRSFF();
		allFF[6] = Exec2.L0RSFF();
		allFF[7] = Exec2.L1RSFF();
		allFF[8] = Exec2.L2RSFF();

		JPanel columns = new JPanel(new GridLayout(1, 6));
		columns.setBackground(bgColor);

		for (int j = 0; j < 2; j++) {
			JPanel gprPanel = new JPanel(new GridLayout(16, 2));
			gprPanel.setBackground(bgColor);
			for (int i = 16 * j; i < 16 * j + 16; i++) {
				JLabel name = new JLabel("R" + i + ": ");
				name.setVerticalAlignment(0);
				name.setHorizontalAlignment(4);
				gprPanel.add(name);
				JPanel val = new JPanel();
				val.setBackground(bgColor);
				regsTextFields[i] = new JTextField(4);
				regsTextFields[i].setText(Integer.toHexString(gpr
						.getRegValue(i)));
				val.add(regsTextFields[i]);
				gprPanel.add(val);
			}
			columns.add(gprPanel);
		}

		JPanel regsPanel1 = new JPanel(new GridLayout(16, 2));
		regsPanel1.setBackground(bgColor);

		for (int i = 0; i < 16; i++) {
			String reg = registers[i];
			JLabel name = new JLabel(reg);
			name.setVerticalAlignment(0);
			name.setHorizontalAlignment(4);
			regsPanel1.add(name);
			regsTextFields[32 + i] = new JTextField(4);
			regsTextFields[32 + i].setText(Integer.toHexString(allRegs[i]
					.getVal()));
			JPanel val = new JPanel();
			val.setBackground(bgColor);
			val.add(regsTextFields[32 + i]);
			regsPanel1.add(val);
		}

		columns.add(regsPanel1);

		JPanel regsPSWPanel = new JPanel(new GridLayout(16, 2));
		regsPSWPanel.setBackground(bgColor);

		for (int i = 0; i < 3; i++) {
			String reg = registers[16 + i];
			JLabel name = new JLabel(reg);
			name.setVerticalAlignment(0);
			name.setHorizontalAlignment(4);
			regsPSWPanel.add(name);
			regsTextFields[48 + i] = new JTextField(4);
			regsTextFields[48 + i].setText(Integer.toHexString(allRegs[16 + i]
					.getVal()));
			JPanel val = new JPanel();
			val.setBackground(bgColor);
			val.add(regsTextFields[48 + i]);
			regsPSWPanel.add(val);
		}

		// columns.add(regsPanel);

		for (int i = 0; i < 9; i++) {
			String reg = ffs[i];
			JLabel name = new JLabel(reg);
			name.setVerticalAlignment(0);
			name.setHorizontalAlignment(4);
			regsPSWPanel.add(name);
			regsTextFields[51 + i] = new JTextField(1);
			Pin out = allFF[i].getOut(0);
			regsTextFields[51 + i]
					.setText(Integer.toHexString(out.isBool() ? (out
							.getBoolVal() ? 1 : 0) : out.getIntVal()));
			JPanel temp = new JPanel();
			temp.setBackground(bgColor);
			temp.add(regsTextFields[51 + i]);
			regsPSWPanel.add(temp);
		}

		for (int i = 0; i < 8; i++) {
			JLabel tmp1 = new JLabel("  ");
			regsPSWPanel.add(tmp1);
		}
		columns.add(regsPSWPanel);

		add(columns, "Center");

		JPanel buttons = new JPanel();
		buttons.setBackground(bgColor);

		JButton changeValues = new JButton("Izmeni");
		changeValues.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				change();
				myMain.updateView();
			}
		});

		buttons.add(changeValues);
		add(buttons, "South");

		addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent arg0) {
				setVisible(false);
			}

		});
		setSize(500, 500);
		setLocation(100, 100);
	}

	private void change() {

		int[] nizvrednosti = new int[60];
		for (int i = 0; i < 60; i++) {
			int val = proverivred(regsTextFields[i].getText(), i);
			if (error) {
				break;
			}
			nizvrednosti[i] = val;
		}

		if (!error) {
			for (int i = 0; i < 32; i++) {
				Adr1.GPR().writeRegValue(i, nizvrednosti[i]);
			}
			for (int i = 0; i < 19; i++) {
				allRegs[i].setVal(nizvrednosti[32 + i]);
			}
			for (int i = 0; i < 9; i++) {
				allFF[i].getOut(0).setBoolVal(
						nizvrednosti[51 + i] == 1 ? true : false);
			}
			potvrda = new JDialog();
			potvrda.setSize(350, 100);
			potvrda.setLocation(200, 200);
			potvrda.setModal(true);
			potvrda.setTitle("Potvrda");
			JPanel osnovni = new JPanel(new GridLayout(2, 1));
			JLabel lab = new JLabel(
					"Promena sadrzaja registara je uspesno odradjena!");
			lab.setHorizontalAlignment(0);
			osnovni.add(lab);
			JButton ok = new JButton("U redu");
			ok.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					potvrda.setVisible(false);

				}
			});
			JPanel tmp = new JPanel();
			tmp.add(ok);
			tmp.setBackground(Color.white);
			osnovni.add(tmp);
			osnovni.setBackground(Color.white);
			potvrda.add(osnovni);
			potvrda.setVisible(true);
			
			//cuvanje simulacije se radi kada se rucno izmeni vrednost nekog od registara
			myMain.saveCriticalMoment();
			myMain.updateView();//npr ako se upise u PC da se na izlazu regitra PC update vrednost registra PC
			myMain.setLabels();//ili gore u uglu za ispis PC da se prikaze odmah nova vrednost
			

		} else {
			error = false;
			greska = new JDialog();
			greska.setSize(550, 150);
			greska.setLocation(200, 200);
			greska.setModal(true);
			greska.setTitle("Greska!");
			JPanel osnovni = new JPanel(new GridLayout(3, 1));
			JLabel lab = new JLabel(
					"Neka od unetih vrednosti nije dobra (ili prelazi velicinu registra ili je unet netacan hex. broj).");
			lab.setHorizontalAlignment(0);
			osnovni.add(lab);
			JLabel lab1 = new JLabel(
					"Zato se brisu sve tekuce izmene registara!");
			lab1.setHorizontalAlignment(0);
			osnovni.add(lab1);
			JButton ok = new JButton("U redu");
			ok.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					greska.setVisible(false);
				}
			}); // idu van opsega
			JPanel tmp = new JPanel();
			tmp.add(ok);
			tmp.setBackground(Color.white);
			osnovni.add(tmp);
			osnovni.setBackground(Color.white);
			greska.add(osnovni);
			greska.setVisible(true);
		}
	}

	private int proverivred(String text, int i) {
		int val;
		try {
			val = Integer.parseInt(text, 16);
		} catch (Exception e) { // ZBOG NUMBER FORMAT EXCEPTION!
			error = true;
			return 0;
		}

		int validBits;
		if (i < 32) {
			validBits = Adr1.GPR().getOut(0).getNumOfLines();
		} else if (i < 51) {
			REG r = allRegs[i - 32];
			if (r.getOut(0).isBool()) {
				validBits = r.getOut().length;
			} else {
				validBits = r.getOut(0).getNumOfLines();
			}
		} else {
			validBits = 1;
		}

		if ((int) Math.pow(2.0D, validBits) <= val) {
			error = true;
		}

		return val;
	}

	public void updateRegistersView() {
		for (int i = 0; i < 32; i++) {
			regsTextFields[i].setText(String.format("%04x", Adr1.GPR()
					.getRegValue(i)));
		}
		for (int i = 32; i < 51; i++) {
			if (i == 33 || i == 34 || i == 35 || i == 37 || i == 38 || i == 39
					|| i == 40 || i == 42 || i == 44 || i == 45 || i == 49) {
				regsTextFields[i].setText(String.format("%02x",
						allRegs[i - 32].getVal()));

			} else {
				regsTextFields[i].setText(String.format("%04x",
						allRegs[i - 32].getVal()));

			}
		}
		for (int i = 51; i < 60; i++) {
			regsTextFields[i].setText(String.format("%01x", allFF[i - 51]
					.getOut(0).getBoolVal() ? 1 : 0));
		}
	}
}
